package cc.mycraft.ds;

import java.util.Random;

import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;

import io.lumine.xikage.mythicmobs.MythicMobs;


public class Spawner {

	private static int MaxNearByEntity;
	private static int SpawnBelow;
	private static int CheckPoints;
	private static int BossChance;
	private static int SpawnTime;
	private static boolean Debug;
	public static World Dungeon;
	public static String DungeonWorrldName;
	private static int TaskID = -1;
	private static int NoPlayerTime = 0;
	
	public static Random r = new Random();
	
	public static void run() {
		load();
		try {
			Dungeon = Bukkit.getWorld(DungeonWorrldName);
			if(Dungeon.getPlayerCount()>0) {
				EnableSpawner();
			}
		} catch (Exception e) {
			return;
		}
	}
	
	public static boolean isEnabled() {
		return TaskID != -1;
	}
	
	public static void EnableSpawner() {
		if(TaskID!=-1) {
			return;
		}
		Dungeon = Bukkit.getWorld(DungeonWorrldName);
		if(Dungeon==null) {
			Bukkit.getLogger().info("未添加地牢世界，不开启刷怪。");
			return;
		} else {
			TaskID = Bukkit.getScheduler().scheduleSyncRepeatingTask(main.getInstance(), SpawnerCheck(), 100, SpawnTime);
			if(Debug) {
				Bukkit.getLogger().info("检测到地牢世界，5秒后开始刷怪。");
			}
		}
	}
	private static void DisableSpawner() {
		if(TaskID!=-1) {
			Bukkit.getScheduler().cancelTask(TaskID);
			TaskID = -1;
			if(Debug) {
				Bukkit.getLogger().info("地牢无人已久，刷怪Task已取消。");
			}
		}
	}
	
	public static void load() {
		MaxNearByEntity = main.getInstance().getConfig().getInt("MaxNearByEntity");
		SpawnBelow = main.getInstance().getConfig().getInt("SpawnBelow");
		CheckPoints = main.getInstance().getConfig().getInt("CheckPoints");
		BossChance = main.getInstance().getConfig().getInt("BossChance");
		SpawnTime = main.getInstance().getConfig().getInt("SpawnTime")*20;
		Debug = main.getInstance().getConfig().getBoolean("Debug");
		DungeonWorrldName = main.getInstance().getConfig().getString("DungeonWorldName");
		Bukkit.getLogger().info("MaxNearBy="+MaxNearByEntity+",SpawnBelow="+SpawnBelow+",CheckPoints="+CheckPoints+",SpawnTime="+SpawnTime+",BossChance="+BossChance);
		
	}
	
	public static Runnable SpawnerCheck() {
		return new Runnable() {
			@Override
			public void run() {
				if(Dungeon.getPlayerCount()<1) {
					NoPlayerTime++;
					if(NoPlayerTime>10) {
						DisableSpawner();
					}
					return;
				}
				for(Player p:Dungeon.getPlayers()) {
					if(p.getLocation().getBlockY()>SpawnBelow) {
						continue;
					}
					if(p.getNearbyEntities(24, 24, 24).size()>MaxNearByEntity) {
						continue;
					}
					spawnTry(p);
				}
			}
		};
	}
	
	public static void spawnTry(Player p) {
		if(!p.getGameMode().equals(GameMode.SURVIVAL)) {
			return;
		}
		int PX = p.getLocation().getBlockX();
		int PY = p.getLocation().getBlockY();
		int PZ = p.getLocation().getBlockZ();
		int spawnY = 10;
		switch (PY/10) {
		case 1: break;
		case 2: spawnY = 20;break;
		case 3: spawnY = 30;break;
		case 4: spawnY = 40;break;
		default:
			return;
		}
		if(Debug) {
			Bukkit.getLogger().info("Try Spawning Mobs for "+p.getName());
		}
		switch (spawnY) {
		case 10:
			pointSpawn(PX,spawnY,PZ,true,14);
			break;
		case 20:
			pointSpawn(PX,spawnY,PZ,false,14);
			break;
		case 30:
			pointSpawn(PX,spawnY,PZ,false,11);
			break;
		default:
			pointSpawn(PX,spawnY,PZ,false,7);
			break;
		}
	
	}
	
	public static void pointSpawn(int X,int Y,int Z,boolean withBoss,int Hard) {
		if(withBoss) {
			for(int i=0;i<CheckPoints;i++) {
				if(adjustSpawnWithBoss(Dungeon.getBlockAt(X+16+r.nextInt(17), Y, Z-8+r.nextInt(17)),Hard)) {
					continue;
				}
				if(adjustSpawnWithBoss(Dungeon.getBlockAt(X-16-r.nextInt(17), Y, Z-8+r.nextInt(17)),Hard)) {
					continue;
				}
				if(adjustSpawnWithBoss(Dungeon.getBlockAt(X-8+r.nextInt(17), Y, Z+16+r.nextInt(17)),Hard)) {
					continue;
				}
				if(adjustSpawnWithBoss(Dungeon.getBlockAt(X-8+r.nextInt(17), Y, Z-16-r.nextInt(17)),Hard)) {
					continue;
				}
			}
		} else {
			for(int i=0;i<CheckPoints;i++) {
				if(adjustSpawn(Dungeon.getBlockAt(X+16+r.nextInt(17), Y, Z-8+r.nextInt(17)),Hard)) {
					continue;
				}
				if(adjustSpawn(Dungeon.getBlockAt(X-16-r.nextInt(17), Y, Z-8+r.nextInt(17)),Hard)) {
					continue;
				}
				if(adjustSpawn(Dungeon.getBlockAt(X-8+r.nextInt(17), Y, Z+16+r.nextInt(17)),Hard)) {
					continue;
				}
				if(adjustSpawn(Dungeon.getBlockAt(X-8+r.nextInt(17), Y, Z-16-r.nextInt(17)),Hard)) {
					continue;
				}
			}
		}
	}
	
	public static boolean adjustSpawnWithBoss(Block B,int Hard) {
		if(Dungeon.getBlockAt(B.getLocation().add(0, -1, 0)).isEmpty()||Dungeon.getBlockAt(B.getLocation().add(0, -1, 0)).isLiquid()) {
			return false;
		}
		if(!Dungeon.getBlockAt(B.getLocation()).isEmpty()) {
			return false;
		}
		if(!Dungeon.getBlockAt(B.getLocation().add(0,1,0)).isEmpty()) {
			return false;
		}
		if(r.nextInt(10001)<BossChance) {
			MythicMobs.inst().getMobManager().spawnMob(DungeonMob.randomBoss(), B.getLocation());
		} else {
			MythicMobs.inst().getMobManager().spawnMob(DungeonMob.randomMob(Hard), B.getLocation());
		}
		if(Debug) {
			Bukkit.getLogger().info("Mob Spawn at "+B.getX()+","+B.getY()+","+B.getZ());
		}
		return true;
	}
	public static boolean adjustSpawn(Block B,int Hard) {
		if(Dungeon.getBlockAt(B.getLocation().add(0, -1, 0)).isEmpty()||Dungeon.getBlockAt(B.getLocation().add(0, -1, 0)).isLiquid()) {
			//Bukkit.getLogger().info("Try Mob Spawn at "+B.getX()+","+B.getY()+","+B.getZ()+" Fail - Air/Liquid");
			return false;
		}
		if(!Dungeon.getBlockAt(B.getLocation()).isEmpty()) {
			//Bukkit.getLogger().info("Try Mob Spawn at "+B.getX()+","+B.getY()+","+B.getZ()+" Fail - not Air Material="+B.getType().toString());
			return false;
		}
		if(!Dungeon.getBlockAt(B.getLocation().add(0,1,0)).isEmpty()) {
			//Bukkit.getLogger().info("Try Mob Spawn at "+B.getX()+","+B.getY()+","+B.getZ()+" Fail - tall<2");
			return false;
		}
		MythicMobs.inst().getMobManager().spawnMob(DungeonMob.randomMob(Hard), B.getLocation());
		if(Debug) {
			Bukkit.getLogger().info("Mob Spawn at "+B.getX()+","+B.getY()+","+B.getZ());
		}
		return true;
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
}
